package com.xiaoyu.lanling.lifecycle

import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.OnLifecycleEvent
import io.reactivex.disposables.Disposable

/**
 * |  event    | Lifecycle.State |
 * | --------- | --------------- |
 * | onCreate  | INITIALIZED     |
 * | onStart   | CREATED         |
 * | onResume  | STARTED         |
 * | onPause   | STARTED         |
 * | onStop    | CREATED         |
 * | onDestroy | DESTROYED       |
 */
fun <T : Disposable> T.disposeOn(lifeCycle: Lifecycle) {

    lifeCycle.addObserver(object : LifecycleObserver {

        @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
        fun onDestroy() {
            this@disposeOn.disposeSafely()
        }
    })
}

fun <T : Disposable> T.disposeOn(lifecycleOwner: LifecycleOwner) {

    lifecycleOwner.lifecycle.addObserver(object : LifecycleObserver {

        @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
        fun onDestroy() {
            this@disposeOn.disposeSafely()
        }
    })
}

fun <T : Disposable> T.disposeOnPause(lifecycleOwner: LifecycleOwner) {
    disposeOnEvent(lifecycleOwner, Lifecycle.Event.ON_PAUSE)
}

internal fun <T : Disposable> T.disposeOnEvent(lifecycleOwner: LifecycleOwner, event: Lifecycle.Event) {
    if (lifecycleOwner.lifecycle.currentState == getState(event)) {
        this.disposeSafely()
    } else
        lifecycleOwner.lifecycle.addObserver(object : LifecycleObserver {

            @OnLifecycleEvent(Lifecycle.Event.ON_ANY)
            fun onEvent(source: LifecycleOwner, lifecycleEvent: Lifecycle.Event) {
                if (lifecycleEvent == event) {
                    this@disposeOnEvent.disposeSafely()
                }
            }
        })
}

internal fun getState(event: Lifecycle.Event): Lifecycle.State {
    return when (event) {
        Lifecycle.Event.ON_CREATE -> Lifecycle.State.INITIALIZED
        Lifecycle.Event.ON_DESTROY -> Lifecycle.State.DESTROYED
        Lifecycle.Event.ON_START -> Lifecycle.State.CREATED
        Lifecycle.Event.ON_RESUME -> Lifecycle.State.STARTED
        Lifecycle.Event.ON_PAUSE -> Lifecycle.State.CREATED
        Lifecycle.Event.ON_STOP -> Lifecycle.State.CREATED
        else -> Lifecycle.State.DESTROYED
    }
}

internal fun <T : Disposable> T.disposeSafely() {
    if (this.isDisposed.not()) {
        dispose()
    }
}